<template>
  <div class="page__bd">
    <div class="weui-gallery" id="gallery" @click="hideimggallery">
        <span v-show="curGalleryType === 'image'" class="weui-gallery__img" id="galleryImg"></span>
        <video v-show="curGalleryType === 'video'" id="galleryVideo" controls="controls" class="weui-gallery__img" style="width:100%;max-height:calc(100vh - 100px);"></video>
        <div class="weui-gallery__opr">
            <a href="javascript:" class="weui-gallery__del" @click="delUpload2">
                <i class="weui-icon-delete weui-icon_gallery-delete"></i>
            </a>
        </div>
    </div>
    <div class="weui-cells weui-cells_form">
      <div class="weui-cell">
          <div class="weui-cell__bd">
              <div class="weui-uploader">
                  <div class="weui-uploader__hd">
                      <p class="weui-uploader__title">图片（视频）上传<span class="red mlp1" v-if="mst">*</span></p>
                      <div class="weui-uploader__info">{{uploaded}}/4</div>
                  </div>
                  <div class="weui-uploader__bd overshow">
                      <ul class="weui-uploader__files" id="uploaderFiles"></ul>
                      <div class="weui-uploader__input-box" id="uploaderInputWrap">
                          <input id="uploaderInput" class="weui-uploader__input" type="file" accept="image/*,video/*" multiple="true" @change="uploadFile" @click="inputfileclick">
                      </div>
                  </div>
              </div>
          </div>
      </div>
    </div>

    <video id="testVideo" controls="controls" preload="load" style="width:100%;max-height:calc(100vh - 100px);display:none;"></video>

    <van-actionsheet v-model="stypePopupShow">
      <van-cell title="图片" @click.native="getImage">
        <van-icon slot="right-icon" name="photo" size="2em" />
      </van-cell>
      <van-cell title="视频" @click.native="getVideo">
        <van-icon slot="right-icon" name="photograph" size="2em" />
      </van-cell>

      <van-cell title="取消" class="mtp1 acenter" @click.native="closeTypeAction"></van-cell>
    </van-actionsheet>
  </div>
</template>

<script>
import wx from 'weixin-js-sdk'
import { AxiosFile } from '@/utils/axios'
import EXIF from 'exif-js'
import { mapMutations } from 'vuex'
export default {
  name: 'MyUploader',
  props: {
    mst: {
      default: false
    }
  },
  data () {
    return {
      binded: false, // 判断是否已绑定事件，防止重复绑定相同事件

      totalUpload: 4,
      uploaded: 0,
      videoFiles: [], // for 视频预览
      failFiles: [], // for 重新上传
      curGallery: '',
      curGalleryID: '',
      curGalleryType: 'image',

      isAndroid: '',
      isiOS: '',

      stypePopupShow: false
    }
  },
  watch: {
    uploaded () {
      if (this.uploaded >= 4) {
        document.querySelector('#uploaderInputWrap').style.display = 'none'
      } else {
        document.querySelector('#uploaderInputWrap').style.display = 'block'
      }
    }
  },
  mounted () {
    let u = navigator.userAgent
    this.isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1 // android终端或者uc浏览器
    this.isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) // ios终端
    // alert('是否是Android：' + isAndroid)
    // alert('是否是iOS：' + isiOS)
    // if (this.isAndroid) {
    //   document.getElementById('uploaderInput').setAttribute('capture', 'camera')
    // }
    if (this.isAndroid) {
      this.wxInit()
    }
  },
  methods: {
    ...mapMutations(['add_user_report_upload_items', 'del_user_report_upload_items']),

    /* 安卓上传 */
    inputfileclick () {
      if (this.isAndroid) {
        event.preventDefault()
        this.openTypeAction()
      }
    },
    openTypeAction () {
      this.stypePopupShow = true
    },
    closeTypeAction () {
      this.stypePopupShow = false
    },

    appendImgDom (imgsrc, tystr) {
      if (tystr !== 'image' && tystr !== 'video') tystr = this.cm.getFileType(tystr)

      var li = document.createElement('li')
      li.setAttribute('class', 'weui-uploader__file weui-uploader__file_status')
      li.setAttribute('ftype', tystr)
      li.setAttribute('style', 'background-image:url(' + imgsrc + ')')

      // 如果是视频保留视频dataurl用于预览
      if (tystr === 'video') {
        var dataurl = document.querySelector('#testVideo').getAttribute('src')
        this.videoFiles.push(dataurl)
        li.setAttribute('vfileIndex', this.videoFiles.length - 1)
      }

      // 删除按钮
      li.innerHTML = '<div style="position:relative;" class="none"><i class="van-icon van-icon-clear" style="font-size:26px;color:red;position:absolute;top:-6px;right:-6px;"></i></div>'

      var div = document.createElement('div')
      div.setAttribute('class', 'weui-uploader__file-content')
      div.innerText = '0%'
      li.appendChild(div)

      document.querySelector('#uploaderFiles').appendChild(li)

      return li
    },

    getImage () {
      this.closeTypeAction()
      let vm = this
      wx.chooseImage({
        count: (this.totalUpload - this.uploaded), // 张数， 默认9
        sizeType: ['compressed'], // 建议压缩图
        sourceType: ['album', 'camera'], // 来源是相册、相机
        success: function (res) { // res.localIds：返回选定照片的本地ID列表，localId可以作为img标签的src属性显示图片
          for (let i = 0; i < res.localIds.length; i++) {
            let file = res.localIds[i]
            let li = vm.appendImgDom(file, 'image')
            li.setAttribute('ftype', 'image')
            vm.uploaded++
            vm.uploadImageToWX(file, li)
          }
        }
      })
    },
    uploadImageToWX (localid, li) {
      li.children[1].innerHTML = '0%'
      li.removeEventListener('click', this.reuploadWX)

      var vm = this
      wx.uploadImage({
        localId: localid,
        success: function (res) {
          vm.saveFromWX(res.serverId, li)
        },
        fail: function (res) {
          vm.uploadFailWX(localid, li)
        }
      })
    },
    getVideo () {
      this.closeTypeAction()
      let vm = this
      wx.invoke('chooseVideo', {
        sourceType: ['album', 'camera'] // 来源是相册、相机
      }, function (res) { // res.localIds：返回选定照片的本地ID列表，localId可以作为img标签的src属性显示图片
        var localIds = typeof res.localIds === 'object' ? res.localIds : JSON.parse(res.localIds) // 返回生成视频的本地ID，需要typeof判断兼容各个终端
        var localId = localIds[0]
        var thumbnail = res.thumbnail // 视频封面缩略图
        let li = vm.appendImgDom(thumbnail, 'image')
        li.setAttribute('ftype', 'video')
        vm.uploaded++
        vm.uploadVideoToWX(localId, li)
      })
    },
    uploadVideoToWX (localid, li) {
      li.children[1].innerHTML = '0%'
      li.removeEventListener('click', this.reuploadWX)

      var vm = this
      wx.invoke('uploadVideo', {
        localId: localid, // 需要上传的视频的本地ID，由chooseVideo接口获得
        isShowProgressTips: 1 // 默认为1，显示进度提示
      }, function (res) {
        var serverId = res.serverId // 返回视频的服务器端ID
        vm.saveFromWX(serverId, li)
      }, function (res) {
        vm.uploadFailWX(localid, li)
      })
    },
    uploadFailWX (localid, li) {
      li.children[1].innerHTML = '<i class="weui-icon-warn"></i>'
      li.addEventListener('click', this.reuploadWX)

      li.setAttribute('localID', localid)

      this.showDelBtn(li)
    },
    reuploadWX (e) {
      let obj = e.target
      while (obj.tagName !== 'LI') {
        obj = obj.parentNode
      }
      // 此时obj就是li

      var localID = obj.getAttribute('localID')
      var uptype = obj.getAttribute('ftype')
      if (uptype === 'image') this.uploadImageToWX(localID, obj)
      else this.uploadVideoToWX(localID, obj)
    },
    saveFromWX (mid, li) {
      li.children[1].innerHTML = '50%'
      li.removeEventListener('click', this.resaveWX)

      this.cm.myajax('/sys/sysoss/uploadFromWeixin', {mediaId: mid}, (data) => {
        this.uploadSucc(data.id, data.url, li)
      }, () => {
        this.saveFailWX(mid, li)
      })
    },
    saveFailWX (mid, li) {
      li.children[1].innerHTML = '<i class="weui-icon-warn"></i>'
      li.addEventListener('click', this.resaveWX)

      li.setAttribute('serverID', mid)

      this.showDelBtn(li)
    },
    resaveWX (e) {
      let obj = e.target
      while (obj.tagName !== 'LI') {
        obj = obj.parentNode
      }
      // 此时obj就是li

      var serverID = obj.getAttribute('serverID')
      this.saveFromWX(serverID, obj)
    },
    uploadSucc (uid, url, li) {
      this.add_user_report_upload_items(uid)
      li.setAttribute('class', 'weui-uploader__file')
      li.setAttribute('uid', uid)
      li.setAttribute('furl', this.cm.getFullFileUrl(url))
      li.removeChild(li.children[1])
      li.addEventListener('click', this.showimggallery)

      // 清理failFiles数组
      var findex = li.getAttribute('fileIndex')
      if (findex !== undefined) {
        findex = parseInt(findex, 10)
        this.failFiles[findex] = ''
      }

      this.showDelBtn(li)
    },

    showimggallery (e) {
      this.curGallery = e.target
      this.curGalleryID = this.curGallery.getAttribute('uid')
      this.curGalleryType = this.curGallery.getAttribute('ftype')
      if (this.curGalleryType === 'image') {
        document.querySelector('#galleryImg').style.backgroundImage = e.target.style.backgroundImage
      } else {
        var furl = this.curGallery.getAttribute('furl')
        if (furl === undefined) {
          var findex = parseInt(this.curGallery.getAttribute('vfileIndex'), 10)
          furl = this.videoFiles[findex]
        }
        document.querySelector('#galleryVideo').setAttribute('src', furl)
      }
      document.querySelector('#gallery').style.display = 'block'
    },
    hideimggallery () {
      document.querySelector('#gallery').style.display = 'none'
      // 视频的话要停止播放
      if (this.curGalleryType === 'video') {
        document.querySelector('#galleryVideo').pause()
      }
    },

    showDelBtn (li) {
      // 显示删除按钮
      li.children[0].setAttribute('class', 'block')
      li.children[0].addEventListener('click', function (e) {
        e.cancelBubble = true
      })
      li.children[0].querySelector('i').addEventListener('click', this.delUpload)
      // 重置文件选择input
      document.querySelector('#uploaderInput').value = ''
    },

    /* IOS上传 */
    uploadFile () {
      var leftu = this.totalUpload - this.uploaded // 最多还能上传leftu个
      var files = document.querySelector('#uploaderInput').files
      for (let i = 0; i < files.length; i++) {
        if (i >= leftu) break
        this.doUploadFile(files[i])
      }
    },
    doUploadFile (file) {
      let ftype = ''
      if (file.type !== '') {
        ftype = this.cm.getFileType(file.type)
      } else {
        ftype = this.cm.getFileType2(file.name)
      }
      if (ftype === 'image') { // 图片
        this.uploaded++
        this.createImgPreview(file, ftype)
      } else if (ftype === 'video') { // 视频
        this.uploaded++
        this.createVideoPreview(file, ftype)
      } else {
        this.$toast('仅支持上传图片或视频')
        // 重置文件选择input
        // document.querySelector('#uploaderInput').value = ''
      }
    },
    createImgPreview (file, ftype) {
      let vm = this
      var orientation = null

      EXIF.getData(file, function () {
        // console.log(EXIF.getAllTags(this))
        orientation = EXIF.getTag(this, 'Orientation')
        vm.repairOrientation(orientation, file, ftype)
      })
    },
    repairOrientation (orientation, file, ftype) {
      let vm = this

      var reader = new FileReader()
      reader.onload = function () {
        var image = new Image()
        image.onload = function () {
          var expectW = this.width || this.naturalWidth
          var expectH = this.height || this.naturalHeight
          if (expectW > expectH && expectW > 800) {
            expectH = 800 * expectH / expectW
            expectW = 800
          } else if (expectH > expectW && expectH > 1200) {
            expectW = 1200 * expectW / expectH
            expectH = 1200
          }

          var canv = document.createElement('canvas')
          var ctx = canv.getContext('2d')
          canv.width = expectW
          canv.height = expectH
          ctx.drawImage(this, 0, 0, expectW, expectH)

          if (orientation && orientation !== 1) {
            switch (orientation) {
              case 6: // 需要顺时针（向左）90度旋转
                vm.rotateImg(this, 'left', canv)
                break
              case 8: // 需要逆时针（向右）90度旋转
                vm.rotateImg(this, 'right', canv)
                break
              case 3: // 需要180度旋转
                vm.rotateImg(this, 'right', canv)
                vm.rotateImg(this, 'right', canv)
                break
            }
          }

          var base64 = canv.toDataURL()

          let li = vm.appendImgDom(base64, ftype)
          vm.uploadTo(file, li)
        }
        image.src = reader.result
      }
      reader.readAsDataURL(file)
    },
    rotateImg (img, direction, canv) {
      var minStep = 0
      var maxStep = 3

      if (!img) return

      var expectW = img.width || img.naturalWidth
      var expectH = img.height || img.naturalHeight
      var step = 2
      if (direction === 'right') {
        step++
        step > maxStep && (step = minStep)
      } else {
        step--
        step < minStep && (step = maxStep)
      }

      var degree = step * 90 * Math.PI / 180
      var ctx = canv.getContext('2d')
      switch (step) {
        case 0:
          canv.width = expectW
          canv.height = expectH
          ctx.drawImage(img, 0, 0)
          break
        case 1:
          canv.width = expectH
          canv.height = expectW
          ctx.rotate(degree)
          ctx.drawImage(img, 0, -expectH)
          break
        case 2:
          canv.width = expectW
          canv.height = expectH
          ctx.rotate(degree)
          ctx.drawImage(img, -expectW, -expectH)
          break
        case 3:
          canv.width = expectH
          canv.height = expectW
          ctx.rotate(degree)
          ctx.drawImage(img, -expectW, 0)
          break
      }
    },
    createVideoPreview (file, ftype) {
      let vm = this
      var reader = new FileReader()
      reader.onload = function () {
        document.querySelector('#testVideo').setAttribute('src', reader.result)
        // document.querySelector('#testVideo').style.display = 'block'
        // document.querySelector('#testVideo').play()

        // 微信浏览器不能自动加载或播放视频，故而不能触发loadeddata事件，需要JS控制视频播放
        function weixinPlay (fn) {
          if (window.WeixinJSBridge) {
            window.WeixinJSBridge.invoke('getNetworkType', {}, fn) // 这句话是在微信中可以自动播放的核心
          } else {
            document.addEventListener('WeixinJSBridgeReady', function () {
              window.WeixinJSBridge.invoke('getNetworkType', {}, fn)
            })
          }
        }
        weixinPlay(function () {
          document.querySelector('#testVideo').play()
          setTimeout(() => {
            document.querySelector('#testVideo').pause()
          }, 100)
        })

        if (!vm.binded) {
          document.querySelector('#testVideo').addEventListener('loadeddata', function () {
            vm.binded = true
            let imgsrc = vm.getVideoThumb()
            let li = vm.appendImgDom(imgsrc, ftype)
            vm.uploadTo(file, li)
          })
        }
      }
      reader.readAsDataURL(file)
    },
    getVideoThumb () {
      const video = document.getElementById('testVideo')
      const canvas = document.createElement('canvas')

      const scale = 0.2
      canvas.width = video.videoWidth * scale
      canvas.height = video.videoHeight * scale
      canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height)

      let imgSrc = canvas.toDataURL('image/png')
      return imgSrc
      // var blob = this.dataURLtoBlob(this.imgSrc, "image/png")//base64转blob，全局函数
      // var file = new File([blob], "video_image.png", { type: "image/png", lastModified: Date.now() })//blob转file
    },

    uploadTo (file, li) {
      let vm = this
      var formfile = new FormData()
      formfile.append('file', file)

      AxiosFile({
        url: '/sys/sysoss/upload',
        data: formfile,
        onUploadProgress: progressEvent => {
          if (progressEvent.lengthComputable) {
            var completed = (progressEvent.loaded / progressEvent.total * 100 | 0) + '%'
            li.querySelector('.weui-uploader__file-content').innerText = completed
          }
        }
      }).then((res) => {
        if (res.data.code === 0) { // 上传成功
          vm.uploadSucc(res.data.obj.id, res.data.obj.url, li)
          vm.cm.errTips(1, '')
        } else { // 上传失败
          vm.uploadFail(file, li)
          vm.cm.errTips(0, res.data.msg)
        }
      }).catch((err) => {
        vm.uploadFail(file, li)
        vm.cm.errTips(-1, err.message)
      })
    },
    uploadFail (file, li) {
      li.children[1].innerHTML = '<i class="weui-icon-warn"></i>'
      li.addEventListener('click', this.reupload)

      this.failFiles.push(file)
      li.setAttribute('fileIndex', this.failFiles.length - 1)

      this.showDelBtn(li)
    },
    reupload (e) {
      let obj = e.target
      while (obj.tagName !== 'LI') {
        obj = obj.parentNode
      }
      // 此时obj就是li

      var findex = parseInt(obj.getAttribute('fileIndex'), 10)
      var file = this.failFiles[findex]

      this.uploadTo(file, obj)
    },

    delUpload (e) {
      e.cancelBubble = true

      var li = e.target.parentNode.parentNode // li元素
      if (li.children.length === 1) { // 删除上传成功者
        var uid = li.getAttribute('uid')
        // this.delUploadedID(uid)
        this.del_user_report_upload_items(uid)
      } else { // 删除上传失败者 清理failFiles数组
        var fileIndex = parseInt(li.getAttribute('fileIndex'), 10)
        this.failFiles[fileIndex] = ''
      }

      // 如果是视频，还需要清理videoFiles数组
      if (li.getAttribute('ftype') === 'video') {
        let findex = parseInt(li.getAttribute('vfileIndex'), 10)
        this.videoFiles[findex] = ''
      }

      document.querySelector('#uploaderFiles').removeChild(li)
      this.uploaded--
    },
    delUpload2 () {
      this.hideimggallery()

      // this.delUploadedID(this.curGalleryID)
      this.del_user_report_upload_items(this.curGalleryID)
      this.uploaded--

      // 如果是视频，还需要清理videoFiles数组
      if (this.curGallery.getAttribute('ftype') === 'video') {
        let findex = parseInt(this.curGallery.getAttribute('vfileIndex'), 10)
        this.videoFiles[findex] = ''
      }

      document.querySelector('#uploaderFiles').removeChild(this.curGallery)
    },

    cleardata () {
      document.querySelector('#uploaderFiles').innerHTML = ''
      document.querySelector('#uploaderInputWrap').style.display = 'block'
      this.uploaded = 0
      this.videoFiles = []
      this.failFiles = []
    },
    appendItem (src, tystr) {
      var li = document.createElement('li')
      li.setAttribute('class', 'weui-uploader__file')
      li.setAttribute('ftype', tystr)
      // 删除按钮
      li.innerHTML += '<div style="position:relative;"><i class="van-icon van-icon-clear" style="font-size:26px;color:red;position:absolute;top:-6px;right:-6px;"></i></div>'

      if (tystr === 'image') {
        li.setAttribute('style', 'background-image:url(' + src + ')')
      } else if (tystr === 'video') {
        li.innerHTML = '<video src="' + src + '" class="videoItem" controls="controls" preload="load"></video>'
      }

      document.querySelector('#uploaderFiles').appendChild(li)
      this.uploaded++

      if (tystr === 'image') {
        li.addEventListener('click', this.showimggallery)
        li.children[0].addEventListener('click', function (e) {
          e.cancelBubble = true
        })
      }
      li.children[0].querySelector('i').addEventListener('click', this.delUpload)
    },
    wxInit () { // weixin-js-jdk 接口注册
      this.cm.myajax('/api/weixin/oauth2/getQySignatureByJsapi', {'url': location.href}, (data) => {
        let conf = data.bean
        wx.config({
          debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来，若要查看传入的参数，可以在pc端打开，参数信息会通过log打出，仅在pc端时才会打印。
          appId: conf.appId, // 必填，公众号的唯一标识
          timestamp: conf.timestamp, // 必填，生成签名的时间戳
          nonceStr: conf.noncestr, // 必填，生成签名的随机串
          signature: conf.signature, // 必填，签名
          jsApiList: ['chooseImage', 'uploadImage', 'chooseVideo', 'uploadVideo'] // 必填，需要使用的JS接口列表
        })

        wx.ready(function () {
          console.log('wx.ready')
          wx.checkJsApi({
            jsApiList: ['chooseImage', 'uploadImage', 'chooseVideo', 'uploadVideo'], // 需要检测的JS接口列表，所有JS接口列表见附录2,
            success: function (res) {
              // 以键值对的形式返回，可用的api值true，不可用为false
              // 如：{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
              console.log(res)
            }
          })
        })

        wx.error(function (res) {
          // config信息验证失败会执行error函数，如签名过期导致验证失败，具体错误信息可以打开config的debug模式查看，也可以在返回的res参数中查看，对于SPA可以在这里更新签名。
          console.log(JSON.stringify(res))
        })
      })
    }
  }
}
</script>

<style lang="stylus" scoped>
.weui-uploader__file
  img
    width 100%
    height 100%
</style>
